package com.avalon.core.service;

import com.avalon.core.condition.Condition;
import com.avalon.core.condition.ConditionOperateEnum;
import com.avalon.core.context.Context;
import com.avalon.core.db.AutoKeyPreparedStatement;
import com.avalon.core.db.AvalonPreparedStatement;
import com.avalon.core.db.DataBaseTools;
import com.avalon.core.db.DynamicJdbcTemplate;
import com.avalon.core.enums.ServiceOperateEnum;
import com.avalon.core.exception.AvalonException;
import com.avalon.core.exception.FieldCheckException;
import com.avalon.core.field.*;
import com.avalon.core.log.IAvalonServiceLog;
import com.avalon.core.log.ServiceLog;
import com.avalon.core.model.Record;
import com.avalon.core.model.*;
import com.avalon.core.alias.AbstractAliasSupport;
import com.avalon.core.alias.IAliasSupport;
import com.avalon.core.module.AbstractModule;
import com.avalon.core.select.builder.SelectBuilder;
import com.avalon.core.select.builder.SelectPageBuilder;
import com.avalon.core.select.builder.SelectTreeBuilder;
import com.avalon.core.tree.SelectOneModel;
import com.avalon.core.tree.SelectOneNode;
import com.avalon.core.tree.SelectOneTree;
import com.avalon.core.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.PostConstruct;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
@Lazy
public abstract class AbstractService implements IAvalonService, IAliasSupport {

    public final static String CREATE_TIME = "createTime";
    public final static String CREATOR = "creator";
    public final static String UPDATE_TIME = "updateTime";
    public final static String UPDATER = "updater";
    public final static String NAME = "name";
    public final static String ID = "id";
    public final static String OPERATE = "op";//系统使用的字段，子类不能使用

    public final static String PARENT_ID_NAME = "parentId";//上级id字段
    public final static String PARENT_PATH_NAME = "parentPath";//上级路径字段 必须使用,id,id, 两边必须改为,不然会出现BUG

    /**
     * 获取当前事物id
     *
     * @return
     */
    public String getTransactionId() {
        return TransactionSynchronizationManager.getCurrentTransactionName() + "." + context.getUUid();
    }

    @Autowired
    private DynamicJdbcTemplate jdbcTemplate;

    @Autowired
    private Context context;

    @Override
    public Boolean getNeedLog() {
        return true;
    }

    private Boolean needLog = null;//缓存提高效率

    protected Boolean canLog() {

        if (ObjectUtils.isNotNull(needLog)) return needLog;

        Boolean result = getNeedLog();
        try {
            IAvalonServiceLog bean = getContext().getAvalonApplicationContext()
                    .getBean(IAvalonServiceLog.class);
        } catch (Exception e) {
            log.info("未实现日志接口,不能记录操作日志");
            result = false;
        }
        return result;
    }

    protected IAvalonServiceLog getServiceLogBean() {
        return getContext().getAvalonApplicationContext()
                .getBean(IAvalonServiceLog.class);
    }

    /**
     * 插入日志
     *
     * @param row
     */
    protected void insertLog(RecordRow row) {
        if (!canLog()) return;
        IAvalonServiceLog serviceLogBean = getServiceLogBean();
        ServiceLog serviceLog = new ServiceLog();
        RecordRow masterRecordRow = getMasterRecordRow(row);
        serviceLog.setServiceId(getPrimaryKeyValue(row));
        serviceLog.setServiceName(getServiceName());
        serviceLog.setHandleId(getContext().getUserId());
        serviceLog.setHandleName(getContext().getUserName());
        serviceLog.setContent(masterRecordRow.convert2Json());
        serviceLog.setOp(ServiceOperateEnum.insert);
        serviceLogBean.insert(serviceLog);
    }

    /**
     * 更新日志
     *
     * @param row
     */
    protected void updateLog(RecordRow row) {
        if (!canLog()) return;
        IAvalonServiceLog serviceLogBean = getServiceLogBean();
        ServiceLog serviceLog = new ServiceLog();
        RecordRow masterRecordRow = getMasterRecordRow(row);
        serviceLog.setServiceId(getPrimaryKeyValue(row));
        serviceLog.setServiceName(getServiceName());
        serviceLog.setHandleId(getContext().getUserId());
        serviceLog.setHandleName(getContext().getUserName());
        serviceLog.setContent(masterRecordRow.convert2Json());
        serviceLog.setOp(ServiceOperateEnum.update);
        serviceLogBean.insert(serviceLog);
    }

    /**
     * 删除日志
     *
     * @param row
     */
    protected void deleteLog(RecordRow row) {
        if (!canLog()) return;
        IAvalonServiceLog serviceLogBean = getServiceLogBean();
        ServiceLog serviceLog = new ServiceLog();
        RecordRow masterRecordRow = getMasterRecordRow(row);
        serviceLog.setServiceId(getPrimaryKeyValue(row));
        serviceLog.setServiceName(getServiceName());
        serviceLog.setHandleId(getContext().getUserId());
        serviceLog.setHandleName(getContext().getUserName());
        serviceLog.setContent(masterRecordRow.convert2Json());
        serviceLog.setOp(ServiceOperateEnum.delete);
        serviceLogBean.insert(serviceLog);
    }


    /**
     * 只获取主表自身的字段值
     *
     * @param row
     * @return
     */
    protected RecordRow getMasterRecordRow(RecordRow row) {
        FieldHashMap fieldMap1 = getMasterFieldMap();
        RecordRow newRow = new RecordRow();
        for (Map.Entry<String, Field> field : fieldMap1.entrySet()) {

            if (row.containsKey(field.getKey())) {
                FieldValue x = new FieldValue(row.getRawValue(field.getKey()));
                if (field.getValue() instanceof IFieldFormat) {
                    x.setField((IFieldFormat) field.getValue());
                }
                newRow.put(field.getKey(), x);
            }
        }
        return newRow;
    }

    @Override
    public String getLabel() {
        return "";
    }

    /**
     * 返回主表字段，排除one2Many one2One字段
     *
     * @return
     */
    public FieldHashMap getMasterFieldMap() {
        Map<String, Field> collect = getFieldMap().entrySet().stream().filter(
                        field -> !(field.getValue() instanceof One2manyField
                                || field.getValue() instanceof One2oneField) &&
                                field.getValue().needLog()
                ).
                collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
        return new FieldHashMap(collect);
    }


    @Override
    public Boolean isLazyLoadField() {
        return false;
    }

    @Override
    public Context getContext() {
        return context;
    }

    public Boolean getNeedDefaultField() {
        return true;
    }

    public Boolean getNeedDefaultKeyField() {
        return true;
    }

    public String getBaseName() {
        return context.getBaseName();
    }

    public Field getNameField() {
        return name;
    }

    private final Field name = createNameField();

    protected Field createNameField() {
        return Fields.createString("名称");
    }

    //  主键
    private final Field id = createPrimaryKeyField();

    protected Field createPrimaryKeyField() {
        return Fields.createInteger("主键", true, true);
    }

    @Override
    public Boolean needDefaultNameField() {
        return true;
    }

    @Override
    public Boolean containOp(RecordRow recordRow) {
        return recordRow.containsKey(OPERATE);
    }

    @Override
    public ServiceOperateEnum getOp(RecordRow recordRow) {

        if (!recordRow.containsKey(OPERATE)) return ServiceOperateEnum.none;
        return ServiceOperateEnum.getFromRecordColumn(recordRow.get(OPERATE));
    }

    /**
     * 动态加载字段 提高系统启动速度 并且实现按需使用模块
     */
    protected void loadField() {
        List<java.lang.reflect.Field> allFieldsList = FieldUtils.getAllFieldsList(this.getClass(), AbstractService.class, Field.class);
        FieldHashMap fieldHashMap = new FieldHashMap();
        allFieldsList.forEach(field -> {
            if (Field.class.isAssignableFrom(field.getType())) {
                field.setAccessible(true);
                if (!needDefaultNameField() && field.getName().equals(NAME)) {
                    return;
                }
                try {
                    if (!fieldHashMap.containsKey(field.getName())) {
                        fieldHashMap.put(field.getName(), (Field) field.get(this));
                    }
                    Method setService = null;
                    Class<?> cls = field.getType();
                    while (cls != Object.class) {//将变量名设置为字段名
                        try {
                            setService = cls.getDeclaredMethod("setService", AbstractService.class);
                            break;
                        } catch (NoSuchMethodException e) {
                            cls = cls.getSuperclass();
                        }
                    }

                    if (setService != null) {
                        setService.setAccessible(true);
                        setService.invoke(field.get(this), this);
                    }

                } catch (IllegalAccessException | InvocationTargetException e) {
                    log.debug(this.getClass() + " postConstruct方法 error->" + e.getMessage());
                }
            }
        });

        if (getNeedDefaultField()) {//需要创建人 创建时间，修改人，修改时间字段
            Field field = Fields.createMany2one("创建人", "base.user", false);
            setFieldService(field);
            fieldHashMap.put(CREATOR, field);
            field = Fields.createDateTime("创建时间");
            setFieldService(field);
            fieldHashMap.put(CREATE_TIME, field);
            field = Fields.createMany2one("修改人", "base.user", false);
            setFieldService(field);
            fieldHashMap.put(UPDATER, field);
            field = Fields.createDateTime("修改时间");
            setFieldService(field);
            fieldHashMap.put(UPDATE_TIME, field);
        }
        if (getNeedDefaultKeyField()) {
            setFieldService(id);
            fieldHashMap.put(ID, id);
        }

        setFieldMap(fieldHashMap);
    }

    private void setFieldService(Field field) {
        try {

            Method setService = null;
            Class<?> cls = field.getClass();
            while (cls != Object.class) {//将变量名设置为字段名
                try {
                    setService = cls.getDeclaredMethod("setService", AbstractService.class);
                    break;
                } catch (NoSuchMethodException e) {
                    cls = cls.getSuperclass();
                }
            }

            if (setService != null) {
                setService.setAccessible(true);
                setService.invoke(field, this);
            }

        } catch (IllegalAccessException | InvocationTargetException e) {
            log.debug(this.getClass() + " postConstruct方法 error->" + e.getMessage());
        }
    }

    @PostConstruct
    public void postConstruct() {//post中不能执行getService方法
        if (!isLazyLoadField()) {
            loadField();
        }
        if (log.isDebugEnabled()) {
            log.debug("service init->" + getServiceName());
        }
        try {
            if (context.getAvalonApplicationContext().isActive()) {
                String firstBeanName = context.getFirstBeanName(this.getClass());
                if (StringUtils.isNotEmpty(firstBeanName) && StringUtils.isNotEmpty(getServiceTableName())) {
                    context.registerAlias(firstBeanName, getServiceName());
                }
            }
        } catch (AvalonException e) {
            log.error("bean 注册别名失败,错误信息->" + e.getMessage());
            log.error(e.getMessage(), e);
        }

        String moduleName = getModuleName();

        if (StringUtils.isNotEmpty(moduleName)) {
            context.putModule(moduleName, this);
        }

    }

    protected String getModuleName() {
        Package module = getClass().getPackage(); //xxx.service
        String moduleName = module.getName();

        moduleName = module.getName();
        int i = moduleName.lastIndexOf("service");
        moduleName = moduleName.substring(0, i - 1); //xxx

        if (context.containsModule(moduleName)) {
            return context.getModuleByPackageName(moduleName).getModuleName();
        }

        Set<Class> scan = ClassScanner.scan(moduleName);
        if (!scan.isEmpty()) {
            for (Class cl : scan) {
                if (!AbstractModule.class.isAssignableFrom(cl)) continue;// AbstractModule 是cl的superclass

                context.getAvalonApplicationContext().getBean(cl);
                return context.getModuleByPackageName(moduleName).getModuleName();
            }
        }
        throw new AvalonException("模块" + moduleName + "未注册");
    }

    private FieldHashMap fieldMap;

    protected void setFieldMap(FieldHashMap fieldMap) {
        this.fieldMap = fieldMap;
    }

    /**
     * 判断字段是否存在
     *
     * @param fieldName
     * @return
     */
    public Boolean containsField(String fieldName) {
        return getFieldMap().containsKey(fieldName);
    }

    public FieldHashMap getFieldMap() {
        if (ObjectUtils.isNull(fieldMap) || fieldMap.isEmpty()) {
            synchronized (this) {
                if (ObjectUtils.isNull(fieldMap) || fieldMap.isEmpty()) {//双重判断
                    loadField();
                }
            }
        }
        return fieldMap;
    }

    /**
     * 获取全部关系字段
     *
     * @return
     */
    public FieldHashMap getRelationFieldMap() {
        Map<String, Field> collect = getFieldMap().entrySet().stream().filter(field -> field.getValue() instanceof RelationField).
                collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
        return new FieldHashMap(collect);
    }

    // 返回非关系、非主键字段
    public FieldHashMap getNotRelationAndPrimaryKeyFieldMap() {
        Map<String, Field> collect = getFieldMap().entrySet().stream().filter(field ->
                !(field.getValue() instanceof RelationField) && !(field.getValue().isPrimaryKey())
        ).collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
        return new FieldHashMap(collect);
    }

    public FieldHashMap getRelationFieldMap(List<String> fields) {
        Map<String, Field> collect = getFieldMap().entrySet().stream().filter(
                        field -> field.getValue() instanceof RelationField && fields.contains(field.getKey())).
                collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
        return new FieldHashMap(collect);
    }

    /**
     * 返回字段 支持及联字段
     *
     * @param name
     * @return
     */
    public Field getField(String name) {
        if (FieldUtils.hasJoinSelect(name)) {
            String tableField = FieldUtils.getJoinFirstTableString(name);
            RelationField field = (RelationField) getFieldMap().get(tableField);
            AbstractService serviceBean = getServiceBean(field.getRelativeServiceName());
            return serviceBean.getField(FieldUtils.getJoinFirstFieldString(name));
        } else {
            return getFieldMap().get(name);
        }
    }

    /**
     * 包含字段
     *
     * @param name
     * @return
     */
    public Boolean containField(String name) {
        if (FieldUtils.hasJoinSelect(name)) {
            String tableField = FieldUtils.getJoinFirstTableString(name);
            FieldHashMap fieldMap1 = getFieldMap();
            if (!fieldMap1.containsKey(tableField)) return false;
            RelationField field = (RelationField) fieldMap1.get(tableField);
            AbstractService serviceBean = getServiceBean(field.getRelativeServiceName());
            return serviceBean.containField(FieldUtils.getJoinFirstFieldString(name));
        } else {
            return getFieldMap().containsKey(name);
        }
    }

    /**
     * 查询满足条件的所有记录 以单表形式返回
     *
     * @param fields
     * @param condition
     * @return
     * @throws AvalonException
     */

    public Record select(List<String> fields, Condition condition) throws AvalonException {
        SelectBuilder selectBuilder = DataBaseTools.selectSql(getService(), FieldUtils.getCommaString(fields), condition);
        AvalonPreparedStatement avalonPrepareStatement =
                createAvalonPrepareStatement(selectBuilder.getSql(), selectBuilder.getFieldValueStatement());
        return jdbcTemplate.select(avalonPrepareStatement, selectBuilder);
    }

    /**
     * 查询满足条件的所有记录 以对象形式返回
     *
     * @param fields
     * @param condition
     * @return 返回值是json形式
     */
    public Record selectWithObject(List<String> fields, Condition condition) {
        SelectBuilder selectBuilder = DataBaseTools.selectSql(getService(), FieldUtils.getCommaString(fields), condition);
        AvalonPreparedStatement avalonPrepareStatement =
                createAvalonPrepareStatement(selectBuilder.getSql(), selectBuilder.getFieldValueStatement());
        return jdbcTemplate.selectObject(avalonPrepareStatement, selectBuilder);
    }

    /**
     * 查询满足条件的所有记录 以对象形式返回
     *
     * @param fields
     * @param condition
     * @return 返回值是json形式
     */
    public Record selectWithObject(String fields, Condition condition) {
        SelectBuilder selectBuilder = DataBaseTools.selectSql(getService(), fields, condition);
        AvalonPreparedStatement avalonPrepareStatement =
                createAvalonPrepareStatement(selectBuilder.getSql(), selectBuilder.getFieldValueStatement());
        return jdbcTemplate.selectObject(avalonPrepareStatement, selectBuilder);
    }

    /**
     * 分页查询满足条件的记录 以对象形式返回
     *
     * @param pageParam
     * @param fields
     * @param order
     * @param conditions
     * @return
     */
    @Override
    public PageInfo selectPageWithObjectExtend(PageParam pageParam,
                                               String fields,
                                               String order,
                                               Boolean isDistinct,
                                               List<PageConditionHigh> conditions) {
        if (ObjectUtils.isEmpty(conditions)) {
            return selectPageWithObject(pageParam, fields, order, isDistinct);
        } else {
            return selectPageWithObject(pageParam, fields, order,
                    isDistinct, getConditionByHighListCondition(conditions));
        }
    }

    /**
     * 分页查询记录 以对象形式返回
     *
     * @param pageParam
     * @param fields
     * @param order
     * @return
     */
    @Override
    public PageInfo selectPageWithObject(PageParam pageParam,
                                         String fields,
                                         String order,
                                         Boolean isDistinct) {
        return selectPageWithObject(pageParam, fields, order, isDistinct, null);
    }

    /**
     * 获取json显示的列表
     *
     * @param pageParam
     * @param fields
     * @param order
     * @param condition
     * @return
     */
    public PageInfo selectPageWithObject(PageParam pageParam,
                                         String fields,
                                         String order,
                                         Boolean isDistinct,
                                         Condition condition) {
        if (StringUtils.isEmpty(fields)) {
            fields = FieldUtils.getCommaString(getAllFieldName());
        } else {
            fields = StringUtils.trim(fields);
        }
        fields = appendPrimaryKey(fields);
        Integer size = context.getApplicationConfig().getPageSize();
        if (ObjectUtils.isNotNull(pageParam.getPageSize())) {
            size = pageParam.getPageSize();
        }
        SelectBuilder selectBuilder = DataBaseTools.selectCountSql(getService(),
                fields,
                condition,
                order,
                isDistinct);
        Integer total = jdbcTemplate.selectCount(selectBuilder.getCountSql(), selectBuilder.getFieldValueStatement());

        SelectPageBuilder selectPageBuilder = new SelectPageBuilder(selectBuilder, pageParam.getPageNum(), size);

        StringBuilder sql = selectPageBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.selectObject(avalonPrepareStatement, selectPageBuilder);

        return new PageInfo(record, total, pageParam.getPageNum(), size);
    }

    public Record select(List<String> fields, Condition condition, String order) throws AvalonException {
        SelectBuilder selectBuilder = DataBaseTools.selectSql(getService(),
                FieldUtils.getCommaString(fields),
                condition,
                order);
        AvalonPreparedStatement avalonPrepareStatement =
                createAvalonPrepareStatement(selectBuilder.getSql(), selectBuilder.getFieldValueStatement());
        return jdbcTemplate.select(avalonPrepareStatement, selectBuilder);
    }

    public Record select(List<String> fields) throws AvalonException {
        return select(fields, null);
    }

    public Record select(String fields) throws AvalonException {
        return select(fields, (Condition) null);
    }

    public Record select(Condition condition) throws AvalonException {
        return select(getAllFieldName(), condition);
    }

    public Record select(String fields, List<PageConditionHigh> pageConditionHighList) throws AvalonException {
        Condition condition = getConditionByHighListCondition(pageConditionHighList);
        return select(fields, condition);
    }

    public Record select(String fields, Condition condition) throws AvalonException {
        return select(Arrays.asList(fields.split(",")), condition);
    }

    public Record select(String fields, Condition condition, String orderBy) throws AvalonException {
        return select(Arrays.asList(fields.split(",")), condition, orderBy);
    }

    public Record selectList(String fields, Map<String, Object> condition) throws AvalonException {
        return select(fields, getPageNormalCondition(condition));
    }

    public Record selectList(String fields, String condition) throws AvalonException {
        return select(fields, Condition.parseRPN(condition));
    }

    public Integer selectCount(String fields, Condition condition, String order) throws AvalonException {
        SelectBuilder selectBuilder = DataBaseTools.selectCountSql(getService(),
                fields,
                condition,
                order,
                null);
        return jdbcTemplate.selectCount(selectBuilder.getCountSql(), selectBuilder.getFieldValueStatement());
    }

    public Integer selectCount(String fields, Condition condition) throws AvalonException {
        return selectCount(fields, condition, null);
    }

    public Integer selectCount(Condition condition) throws AvalonException {
        return selectCount("id", condition, null);
    }

    @Override
    public PageInfo selectPage(PageParam pageParam,
                               String fields,
                               String order,
                               Boolean isDistinct,
                               Condition condition) throws AvalonException {
        if (StringUtils.isEmpty(fields)) {
            fields = FieldUtils.getCommaString(getAllFieldName());
        } else {
            fields = StringUtils.trim(fields);
        }
        fields = appendPrimaryKey(fields);
        Integer size = context.getApplicationConfig().getPageSize();
        if (ObjectUtils.isNotNull(pageParam.getPageSize())) {
            size = pageParam.getPageSize();
        }
        SelectBuilder selectBuilder = DataBaseTools.selectCountSql(getService(),
                fields,
                condition,
                order,
                isDistinct);
        Integer total = jdbcTemplate.selectCount(selectBuilder.getCountSql(), selectBuilder.getFieldValueStatement());

        SelectPageBuilder selectPageBuilder = new SelectPageBuilder(selectBuilder, pageParam.getPageNum(), size);

        StringBuilder sql = selectPageBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectPageBuilder);

        return new PageInfo(record, total, pageParam.getPageNum(), size);
    }


    /**
     * 分页查询
     *
     * @param pageParam
     * @return
     * @throws AvalonException
     */
    @Override
    public PageInfo selectPage(PageParam pageParam,
                               String fields,
                               String order,
                               Boolean isDistinct) throws AvalonException {
        return selectPage(pageParam, fields, order, isDistinct, null);
    }

    @Override
    public PageInfo selectPageNormal(PageParam pageParam,
                                     String fields,
                                     Map<String, Object> condition,
                                     String order,
                                     Boolean isDistinct) throws AvalonException {

        Condition con = getPageNormalCondition(condition);
        return selectPage(pageParam, fields, order, isDistinct, con);
    }

    protected Condition getPageNormalCondition(Map<String, Object> condition) throws AvalonException {

        if (ObjectUtils.isEmpty(condition)) return null;

        Condition con = null;
        for (Map.Entry<String, Object> keyValue : condition.entrySet()) {
            if (ObjectUtils.isEmpty(keyValue.getValue())) {
                continue;
            }
            Field field = getField(keyValue.getKey());
            Object value = keyValue.getValue();
            if (field instanceof IFieldFormat) {
                value = field.parse(value);
            }
            if (ObjectUtils.isNull(con)) {
                con = Condition.equalCondition(keyValue.getKey(), value);
            } else {
                con = con.andCondition(Condition.equalCondition(keyValue.getKey(), value));
            }
        }

        return con;

    }

    /**
     * @param pageParam
     * @param fields
     * @param conditions
     * @return
     */
    @Override
    public PageInfo selectPageCondition(PageParam pageParam,
                                        String fields,
                                        String order,
                                        Boolean isDistinct,
                                        List<PageCondition> conditions) throws AvalonException {

        if (ObjectUtils.isEmpty(conditions)) {
            return selectPage(pageParam, fields, order, isDistinct, null);
        } else {

            Condition x = null;
            for (Condition condition : conditions) {
                if (ObjectUtils.isEmpty(condition.getValue())) {
                    continue;
                }
                condition = condition.convertAdapterCondition();
                condition.parse(getService());
                if (ObjectUtils.isNull(x)) {
                    x = condition;
                } else {
                    x = x.andCondition(condition);
                }
            }

            return selectPage(pageParam, fields, order, isDistinct, x);
        }
    }

    @Override
    public PageInfo selectPageConditionHigh(PageParam pageParam,
                                            String fields,
                                            String order,
                                            Boolean isDistinct,
                                            List<PageConditionHigh> conditions) throws AvalonException {

        if (ObjectUtils.isEmpty(conditions)) {
            return selectPage(pageParam, fields, order, isDistinct);
        } else {
            return selectPage(pageParam, fields, order, isDistinct, getConditionByHighListCondition(conditions));
        }
    }

    public Condition getConditionByHighListCondition(List<PageConditionHigh> conditions) {
        Condition x = null;
        PageConditionHigh preCondition = null;
        for (PageConditionHigh condition : conditions) {
            if (ObjectUtils.isEmpty(condition.getValue())) {
                continue;
            }
            Condition newCondition = condition.convertAdapterCondition();
            newCondition.parse(getService());
            if (ObjectUtils.isNull(x)) {
                x = newCondition;
            } else {
                if (preCondition.getConnector() == ConditionOperateEnum.Or) {
                    x = x.orCondition(newCondition);
                } else {
                    x = x.andCondition(newCondition);
                }
            }
            preCondition = condition;
        }
        return x;
    }

    /**
     * 获取指定字段的值
     *
     * @param fields
     * @param id
     * @return
     */
    public RecordRow selectOne(String fields, Object id) throws AvalonException {
        return selectOne(fields, Condition.equalCondition(getPrimaryKeyName(), id));
    }

    public RecordRow selectOne(List<String> fieldList, Integer id) throws AvalonException {
        String fields = null;
        if (ObjectUtils.isNotEmpty(fieldList)) {
            fields = FieldUtils.getCommaString(fieldList);
        }
        return selectOne(fields, id);
    }

    public RecordRow selectOne(Condition condition, List<String> fieldList) throws AvalonException {
        String fields = null;
        if (ObjectUtils.isNotEmpty(fieldList)) {
            fields = FieldUtils.getCommaString(fieldList);
        }
        return selectOne(fields, condition);
    }

    public RecordRow selectOneNoLevel(List<String> fieldList, Condition condition, String order) throws AvalonException {
        String fields = null;
        if (ObjectUtils.isNotEmpty(fieldList)) {
            fields = FieldUtils.getCommaString(fieldList);
        }
        return selectOneNoLevel(fields, condition, order);
    }

    public Record selectNoLevel(String fields, Condition condition, String order) throws AvalonException {

        if (StringUtils.isEmpty(fields)) {
            fields = FieldUtils.getCommaString(getAllFieldName());
        } else {
            fields = StringUtils.trim(fields);
        }
        fields = appendPrimaryKey(fields);

        SelectBuilder selectBuilder = DataBaseTools.selectAllSql(getService(), fields, condition, order, null);
        StringBuilder sql = selectBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectBuilder);
        if (ObjectUtils.isEmpty(record)) {
            return new Record();
        }
        return record;
    }

    public RecordRow selectOneNoLevel(String fields, Condition condition, String order) throws AvalonException {
        PageParam pageParam = new PageParam();
        pageParam.setPageNum(1);
        pageParam.setPageSize(1);

        if (StringUtils.isEmpty(fields)) {
            fields = FieldUtils.getCommaString(getAllFieldName());
        } else {
            fields = StringUtils.trim(fields);
        }
        fields = appendPrimaryKey(fields);
        Integer size = pageParam.getPageSize();

        SelectBuilder selectBuilder = DataBaseTools.selectCountSql(getService(),
                fields,
                condition,
                order,
                null);

        SelectPageBuilder selectPageBuilder = new SelectPageBuilder(selectBuilder, pageParam.getPageNum(), size);

        StringBuilder sql = selectPageBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectPageBuilder);

        if (ObjectUtils.isEmpty(record)) {
            return new RecordRow();
        }
        return record.get(0);
    }

    /**
     * 获取一条数据，同时没有及联
     *
     * @return
     */
    public RecordRow selectOneNoLevel(String fields, List<PageConditionHigh> conditions, String order) throws AvalonException {
        Condition condition = getConditionByHighListCondition(conditions);
        return selectOneNoLevel(fields, condition, order);
    }

    public AvalonPreparedStatement createAvalonPrepareStatement(StringBuilder sql, FieldValueStatement valueStatement) throws AvalonException {
        return new AvalonPreparedStatement(getService(), sql, valueStatement);
    }

    /**
     * 扩张主键字段
     *
     * @param fields
     * @return
     */
    private String appendPrimaryKey(String fields) {
        if (StringUtils.isEmpty(fields)) return fields;

        if (!FieldUtils.getFieldList(fields).contains(getPrimaryKeyName()))
            return fields + "," + getPrimaryKeyName();

        return fields;
    }

    /**
     * 将字段转换为树字段，进行及联查询
     *
     * @param fields
     * @return
     */
    private SelectOneTree getSelectTreeFromField(String fields) {
        List<String> fieldList = new ArrayList<>(FieldUtils.getFieldList(fields));
        SelectOneTree selectOneTree = new SelectOneTree();
        SelectOneModel selectOneModel = new SelectOneModel();
        selectOneModel.setService(getService());
        selectOneTree.setData(selectOneModel);//设置主表作为根节点

        for (String s : fieldList) {//遍历字段,并且分类字段
            selectOneTree.addChildren(s, getService(), selectOneTree);
        }

        return selectOneTree;
    }


    public RecordRow selectOneDo(SelectOneNode selectOneNode, Condition condition) throws AvalonException {

        SelectOneModel data = selectOneNode.getData();
        AbstractService service = data.getService();
        String fields = "";
        if (ObjectUtils.isNotEmpty(data.getFieldList())) {
            fields = FieldUtils.getCommaString(data.getFieldList());
        }

        SelectBuilder selectBuilder = DataBaseTools.selectSql(service, fields, condition);
        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(selectBuilder.getSql(),
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectBuilder);

        if (ObjectUtils.isNull(record) || record.size() == 0) return new RecordRow();

        RecordRow recordRow = record.get(0);
        if (!recordRow.containsKey(getPrimaryKeyName())) return recordRow;

        List<SelectOneNode> children = selectOneNode.getChildren();

        if (ObjectUtils.isEmpty(children)) return recordRow;
        Object primaryKeyValue = service.getPrimaryKeyValue(recordRow);
        for (SelectOneNode treeNode : children) {
            SelectOneModel model = treeNode.getData();

            Field field = model.getField();//子表字段 用于记录和主表的关系
            if (field instanceof One2oneField) {
                AbstractService childService = model.getService();
                RecordRow row = childService.selectOneDo(treeNode,
                        Condition.equalCondition(((One2oneField) field).getRelativeFieldName(), primaryKeyValue));
                recordRow.put(field.getName(), row);
            } else if (field instanceof One2manyField) {
                String relativeFieldName = ((One2manyField) field).getRelativeFieldName();
                Record record1 = model.getService().select("id", Condition.equalCondition(relativeFieldName,
                        getPrimaryKeyValue(recordRow)));

                Record recordRows = new Record();
                record1.forEach(recordRow1 -> {
                    RecordRow recordRow2 = model.getService().selectOneDo(treeNode,
                            Condition.equalCondition(model.getService().getPrimaryKeyName(),
                                    model.getService().getPrimaryKeyValue(recordRow1)));
                    recordRows.add(recordRow2);
                });
                recordRow.put(field.getName(), recordRows);
            }
        }

        return recordRow;
    }

    public RecordRow selectOne(String fields, Condition condition) throws AvalonException {
        if (StringUtils.isEmpty(fields)) {
            fields = FieldUtils.getCommaString(getAllFieldName(true));
        } else {
            fields = appendPrimaryKey(fields);
        }

        SelectOneTree selectOneTree = getSelectTreeFromField(fields);

        return selectOneDo(selectOneTree, condition);
    }


    public RecordRow selectOne(Integer id) throws AvalonException {
        return selectOne(Condition.equalCondition(getPrimaryKeyName(), id));
    }

    public RecordRow selectOne(Integer id, List<Field> fieldList) throws AvalonException {
        StringBuilder fieldNames = new StringBuilder();
        fieldList.forEach(f -> {
            if (fieldNames.length() > 0) {
                fieldNames.append(",");
            }
            fieldNames.append(f.getName());
        });
        return selectOne(fieldNames.toString(), Condition.equalCondition(getPrimaryKeyName(), id));
    }

    public RecordRow selectOne(Integer id, Field... fields) throws AvalonException {
        StringBuilder fieldNames = new StringBuilder();
        for (Field field : fields) {
            if (fieldNames.length() > 0) {
                fieldNames.append(",");
            }
            fieldNames.append(field.getName());
        }
        return selectOne(fieldNames.toString(), Condition.equalCondition(getPrimaryKeyName(), id));
    }

    public RecordRow selectOne(Condition condition, Field... fields) {
        StringBuilder fieldNames = new StringBuilder();
        for (Field field : fields) {
            if (fieldNames.length() > 0) {
                fieldNames.append(",");
            }
            fieldNames.append(field.getName());
        }
        return selectOne(fieldNames.toString(), condition);
    }

    public RecordRow selectOne(Condition condition) throws AvalonException {
        return selectOne(null, condition);
    }

    /**
     * 删除记录 不会检查
     *
     * @param id
     * @return
     * @throws AvalonException
     */
    public Integer delete(Object id) throws AvalonException {
        StringBuilder sql = DataBaseTools.deleteSql(getServiceBean(getServiceName()), id);
        RecordRow row = new RecordRow();
        row.put("id", id);
        deleteLog(row);
        return jdbcTemplate.delete(sql);
    }

    /**
     * 条件删除 会检查记录是否存在
     *
     * @param condition
     * @return
     * @throws AvalonException
     */
    public Integer delete(Condition condition, String serviceName) throws AvalonException {
        AbstractService serviceBean = getServiceBean(serviceName);

        Record record = serviceBean.select("id", condition);

        if (ObjectUtils.isNotEmpty(record)) {
            for (RecordRow row : record) {
                RecordRow one = serviceBean.selectOne(row.getInteger(serviceBean.getPrimaryKeyField()));
                serviceBean.delete(one);
            }
            return record.size();
        }
        return 0;
    }

    public Integer delete(Condition condition) throws AvalonException {
        Record record = select("id", condition);
        if (ObjectUtils.isNotEmpty(record)) {
            for (RecordRow row : record) {
                RecordRow one = selectOne(row.getInteger(getPrimaryKeyField()));
                delete(one);
            }
            return record.size();
        }
        return 0;
    }

    /**
     * 删除记录 会检查当前记录
     *
     * @param row
     * @return
     * @throws AvalonException
     */
    public Integer delete(RecordRow row) throws AvalonException {
        Integer id = (Integer) getPrimaryKeyValue(row);
        checkDelete(row);

        FieldHashMap relationFieldMap = getRelationFieldMap();
        for (Map.Entry<String, Field> fieldEntry : relationFieldMap.entrySet()) {//处理子表
            String key = fieldEntry.getKey();
            RelationField field = (RelationField) fieldEntry.getValue();

            RecordColumn recordColumn = row.get(getPrimaryKeyName());
            if (ObjectUtils.isNull(recordColumn)) continue;

            if (field instanceof One2manyField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());

                Record record = row.getRecord(field);
                if (ObjectUtils.isNotEmpty(record)) {
                    serviceBean.deleteMulti(record);
                }
            }

            if (field instanceof One2oneField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());
                RecordRow oneRow = row.getRecordRow(field);
                if (ObjectUtils.isNotEmpty(oneRow)) {
                    serviceBean.delete(oneRow);
                }
            }
        }

        return delete(id);
    }

    protected void checkDelete(RecordRow recordRow) throws AvalonException {

    }

    public Integer deleteMulti(List<Integer> ids) throws AvalonException {
        Integer count = 0;
        for (Integer id : ids) {
            count += delete(id);
        }
        return count;
    }

    public Integer deleteMulti(Record record) throws AvalonException {
        Integer count = 0;
        for (RecordRow row : record) {
            count += delete(row);
        }
        return count;
    }

    public PrimaryKey insert(RecordRow recordRow) throws AvalonException {
        if (getNeedDefaultField()) {
            if (!recordRow.containsKey(CREATE_TIME)) {
                recordRow.put(CREATE_TIME, new RecordColumn(DateTimeUtils.getCurrentDate()));
            }
            if (!recordRow.containsKey(CREATOR)) {
                Integer userId = context.getUserId();
                if (ObjectUtils.isNotNull(userId)) {
                    recordRow.put(CREATOR, new RecordColumn(context.getUserId()));
                }
            }
        }

        //增加默认值
        RecordRow defaultValueAll = this.getDefaultValueAll();

        defaultValueAll.forEach(((name, value) -> {
            if (ObjectUtils.isNotNull(value.getValue())) {
                if (!recordRow.containsKey(name)) {
                    recordRow.put(name, value);
                } else {

                    if (ObjectUtils.isNull(recordRow.get(name))) {
                        recordRow.put(name, value);
                        return;
                    }

                    if (ObjectUtils.isEmpty(recordRow.get(name).getValue())) {
                        recordRow.put(name, value);
                    }
                }
            }
        }));

        checkBeforeInsert(recordRow);
        // 判断是否可以保存
        checkInsert(recordRow);

        FieldValueStatement fieldValueStatement = new FieldValueStatement();
        StringBuilder sql = DataBaseTools.insertSql(getService(), recordRow,
                fieldValueStatement);//返回主键

        AvalonPreparedStatement autoKeyPreparedStatement = null;

        Object masterId;
        if (getPrimaryKeyField().isAutoIncrement()) {
            KeyHolder keyHolder = new GeneratedKeyHolder();
            autoKeyPreparedStatement = new AutoKeyPreparedStatement(getService(),
                    sql, fieldValueStatement);
            masterId = jdbcTemplate.insert(autoKeyPreparedStatement, keyHolder);
        } else {
            autoKeyPreparedStatement = new AvalonPreparedStatement(getService(),
                    sql, fieldValueStatement);
            jdbcTemplate.insert(autoKeyPreparedStatement);
            masterId = getPrimaryKeyValue(recordRow);
        }

        recordRow.put(getPrimaryKeyName(), masterId);
        insertLog(recordRow);
        checkAfterInsert(recordRow);
        FieldHashMap relationFieldMap = getRelationFieldMap();

        for (Map.Entry<String, Field> fieldEntry : relationFieldMap.entrySet()) {//处理子表
            String key = fieldEntry.getKey();
            RelationField field = (RelationField) fieldEntry.getValue();

            RecordColumn recordColumn = recordRow.get(key);
            if (ObjectUtils.isNull(recordColumn)) continue;

            if (field instanceof One2manyField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());
                String relativeFieldName = field.getRelativeFieldName();
                Record record = recordColumn.getRecord();

                record.putAll(relativeFieldName, masterId);//子表外键赋值
                serviceBean.insertMulti(record);
            } else if (field instanceof One2oneField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());
                String relativeFieldName = field.getRelativeFieldName();
                RecordRow recordRow1 = recordColumn.getRecordRow();

                recordRow1.put(relativeFieldName, masterId);//子表外键赋值
                serviceBean.insert(recordRow1);
            }
        }

        return PrimaryKey.build(masterId);
    }

    /**
     * description: 插入之后验证字段数据是否重复，如果有两条重复值，表示重复插入
     * version: 1.0
     * date: 2022/4/12 17:49
     * author: AN
     *
     * @param primaryKeyName 主键 名称
     * @param field
     * @param condition
     * @param recordColumn
     * @return void
     */
    public void checkBeforeInsertRepeat(String primaryKeyName, Field field, Condition condition, RecordColumn recordColumn) throws AvalonException {

        Integer count = selectCount(primaryKeyName, condition);

        if (count >= 2) {
            throw new FieldCheckException(field, field.getLabel() + "：" + recordColumn.getValue() + "，已经存在");
        }
    }

    /**
     * 更新之前检查重名，排除自身id之后，有一条数据，表示重复
     *
     * @param primaryKeyName 主键 名称
     * @param field          字段
     * @param condition      条件
     * @param recordColumn
     * @param id             主键值
     * @throws AvalonException
     */
    public void checkBeforeUpdateRepeat(String primaryKeyName, Field field, Condition condition, RecordColumn recordColumn, Object id) throws AvalonException {


        Condition con = condition.andCondition(Condition.notEqualCondition(getPrimaryKeyName(), id));
        Integer count = selectCount(primaryKeyName, con);
        if (count >= 1) {
            throw new FieldCheckException(field, field.getLabel() + "：" + recordColumn.getValue() + "，已经存在");
        }
    }

    /**
     * 更新之前
     *
     * @param recordRow
     * @throws AvalonException
     */

    protected void checkBeforeInsert(RecordRow recordRow) throws AvalonException {
        checkUniqueField(recordRow);
    }

    @Override
    public FieldHashMap getUniqueFiled() {
        Map<String, Field> collect = getFieldMap().entrySet().stream().filter(field -> field.getValue().isUnique()).
                collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
        return new FieldHashMap(collect);
    }

    @Override
    public Boolean hasRelationTable() {
        return getRelationFieldMap().size() != 0;
    }

    /**
     * 检查更新之后
     *
     * @param recordRow
     * @throws AvalonException
     */
    protected void checkAfterInsert(RecordRow recordRow) throws AvalonException {

    }

    private void checkUniqueField(RecordRow recordRow) throws AvalonException {
        FieldHashMap uniqueFiled = getUniqueFiled();
        if (uniqueFiled.size() > 0) {
            for (Map.Entry<String, Field> fieldEntry : uniqueFiled.entrySet()) {
                String key = fieldEntry.getKey();
                Field field = fieldEntry.getValue();
                if (recordRow.containsKey(key)) {
                    RecordColumn recordColumn = recordRow.get(key);

                    Condition condition = Condition.equalCondition(key, recordColumn.getValue());
                    if (recordRow.containsKey(getPrimaryKeyName())) {
                        condition = condition.andCondition(Condition.notEqualCondition(getPrimaryKeyName(),
                                recordRow.get(getPrimaryKeyName()).getValue()));
                    }
                    Integer count = selectCount("id", condition);

                    if (count >= 1) {
                        throw new FieldCheckException(field, field.getLabel() + "：" + recordColumn.getValue() + "，已经存在");
                    }
                }
            }
        }
    }

    /**
     * 新增之前检查，报错 则无法创建
     *
     * @param recordRow
     * @throws AvalonException
     */
    protected void checkInsert(RecordRow recordRow) throws AvalonException {
        checkRequiredField(recordRow);
    }

    protected void checkRequiredField(RecordRow recordRow) {
        FieldHashMap requiredFields = getIsRequiredAll();

        for (Map.Entry<String, Field> fieldEntry : requiredFields.entrySet()) {
            if (fieldEntry.getValue().isPrimaryKey()) continue;
            if (RecordColumnUtils.isEmpty(recordRow.get(fieldEntry.getKey()))) {
                throw new FieldCheckException(getServiceName(), fieldEntry.getValue(), fieldEntry.getValue().getLabel() + "为必填项");
            }
        }
    }

    /**
     * 更新之前检查，报错 则无法更新
     *
     * @param recordRow
     * @throws AvalonException
     */
    protected void checkBeforeUpdate(RecordRow recordRow) throws AvalonException {

    }

    /**
     * 更新之后检查，报错 则无法更新
     *
     * @param recordRow
     * @throws AvalonException
     */
    protected void checkAfterUpdate(RecordRow recordRow) throws AvalonException {

    }

    /**
     * 更新之前
     *
     * @param recordRow
     * @throws AvalonException
     */

    protected void checkUpdate(RecordRow recordRow) throws AvalonException {
        checkUniqueField(recordRow);
    }

    public List<Object> insertMulti(Record record) throws AvalonException {
        ArrayList<Object> ids = new ArrayList<>();
        for (RecordRow recordRow : record) {
            ids.add(insert(recordRow));
        }
        return ids;
    }

    /**
     * 根据条件更新表，只更新单表
     *
     * @param recordRow
     * @param condition
     * @return
     * @throws AvalonException
     */
    public Integer update(RecordRow recordRow, Condition condition) throws AvalonException {
        if (getNeedDefaultField()) {
            recordRow.put(UPDATE_TIME, new RecordColumn(DateTimeUtils.getCurrentDate()));
            recordRow.put(UPDATER, new RecordColumn(context.getUserId()));
        }
        FieldValueStatement fieldValueStatement = new FieldValueStatement();
        StringBuilder sql = DataBaseTools.updateSql(getService(), recordRow, condition, fieldValueStatement);

        AvalonPreparedStatement avalonPreparedStatement =
                new AutoKeyPreparedStatement(getService(), sql, fieldValueStatement);

        return jdbcTemplate.update(avalonPreparedStatement);
    }

    public Integer update(RecordRow recordRow) throws AvalonException {
        if (getNeedDefaultField()) {
            recordRow.put(UPDATE_TIME, new RecordColumn(DateTimeUtils.getCurrentDate()));
            recordRow.put(UPDATER, new RecordColumn(context.getUserId()));
        }
        checkBeforeUpdate(recordRow);
        // 判断是否可以更新
        checkUpdate(recordRow);
        FieldValueStatement fieldValueStatement = new FieldValueStatement();
        StringBuilder sql = DataBaseTools.updateSql(getService(), recordRow, fieldValueStatement);

        AvalonPreparedStatement avalonPreparedStatement =
                new AutoKeyPreparedStatement(getService(), sql, fieldValueStatement);
        Integer count = jdbcTemplate.update(avalonPreparedStatement);
        updateLog(recordRow);//记录日志
        FieldHashMap relationFieldMap = getRelationFieldMap();
        for (Map.Entry<String, Field> fieldEntry : relationFieldMap.entrySet()) {//处理子表
            String key = fieldEntry.getKey();
            RelationField field = (RelationField) fieldEntry.getValue();

            RecordColumn recordColumn = recordRow.get(key);
            if (ObjectUtils.isNull(recordColumn)) continue;

            if (field instanceof One2manyField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());
                String relativeFieldName = field.getRelativeFieldName();
                Record record = recordColumn.getRecord();

                record.putAll(relativeFieldName, getPrimaryKeyValue(recordRow));//子表外键赋值

                for (RecordRow row : record) {
                    ServiceOperateEnum op = serviceBean.getOp(row);
                    switch (op) {
                        case insert -> serviceBean.insert(row);
                        case update -> serviceBean.update(row);
                        case del, delete -> serviceBean.delete(row);
                    }
                }
            } else if (field instanceof One2oneField) {
                AbstractService serviceBean =
                        context.getServiceBean(field.getRelativeServiceName());
                String relativeFieldName = field.getRelativeFieldName();
                RecordRow recordRow1 = recordColumn.getRecordRow();
                recordRow1.put(relativeFieldName, getPrimaryKeyValue(recordRow));
                ServiceOperateEnum op = serviceBean.getOp(recordRow1);
                switch (op) {
                    case insert -> serviceBean.insert(recordRow1);
                    case update -> serviceBean.update(recordRow1);
                    case del, delete -> serviceBean.delete(recordRow1);
                }
            }
        }

        checkAfterUpdate(recordRow);
        return count;
    }


    /**
     * 获取主键的值
     *
     * @param row
     * @return
     */
    public Object getPrimaryKeyValue(RecordRow row) {
        if (getPrimaryKeyField() instanceof BigIntegerField) {
            return row.get(getPrimaryKeyName()).getLong();
        }

        return row.get(getPrimaryKeyName()).getInteger();
    }

    public Object getPrimaryKeyValue(PrimaryKey primaryKey) {
        if (getPrimaryKeyField() instanceof BigIntegerField) {
            return primaryKey.getLong();
        }

        return primaryKey.getInteger();
    }

    private List<Field> fieldList;

    public List<Field> getFields() {
        if (!ObjectUtils.isNull(fieldList)) {
            return fieldList;
        }
        synchronized (this) {
            if (!ObjectUtils.isNull(fieldList)) {
                return fieldList;
            }
            fieldList = new ArrayList<>();
            for (Map.Entry<String, Field> item : getFieldMap().entrySet()) {
                fieldList.add(item.getValue());
            }
            return fieldList;
        }
    }

    public Integer updateMulti(Record record) throws AvalonException {
        Integer count = 0;
        for (RecordRow recordRow : record) {
            count += update(recordRow);
        }
        return count;
    }

    public abstract String getServiceName();

    public String getServiceTableName() {
        return Fields.dot2UnderscoreName(getServiceName());
    }

    private String primaryKeyName;//


    public String getPrimaryKeyName() {

        if (!StringUtils.isEmpty(primaryKeyName)) {
            return primaryKeyName;
        }

        synchronized (this) {
            if (!StringUtils.isEmpty(primaryKeyName)) {
                return primaryKeyName;
            }
            for (Map.Entry<String, Field> item : getFieldMap().entrySet()) {
                if (item.getValue().isPrimaryKey()) {
                    primaryKeyName = item.getKey();
                    break;
                }
            }
            return primaryKeyName;
        }
    }

    public Type getPrimaryKeyType() {
        return getFieldMap().get(getPrimaryKeyName()).getFieldType();
    }

    public Field getPrimaryKeyField() {
        return getFieldMap().get(getPrimaryKeyName());
    }

    public List<String> clearRelationField(List<String> fields) {
        List<String> list = new ArrayList<>();
        for (String s : fields) {
            Field field = getField(s);
            if (field instanceof One2manyField) {
                continue;
            } else if (field instanceof One2oneField) {
                continue;
            }
            list.add(s);
        }
        return list;
    }

    public List<String> clearRelationField(String fields) {
        if (StringUtils.isEmpty(fields)) return null;
        return clearRelationField(List.of(fields.split(",")));
    }

    /**
     * 默认不包括One2manyField和One2oneField
     *
     * @return
     */
    public List<String> getAllFieldName() {
        return getAllFieldName(false);
    }

    /**
     * 带上关联字段
     *
     * @param withRelation
     * @return
     */
    public List<String> getAllFieldName(Boolean withRelation) {

        List<String> fieldNames = new ArrayList<>();

        for (Map.Entry<String, Field> item : getFieldMap().entrySet()) {
            if (item.getValue() instanceof One2manyField) {
                if (!withRelation) continue;
            } else if (item.getValue() instanceof Many2manyField) {
                continue;
            } else if (item.getValue() instanceof One2oneField) {
                if (!withRelation) continue;
            }
            fieldNames.add(item.getKey());
        }

        return fieldNames;
    }

    /**
     * 创建数据库表
     */
    public void createTable() {
        StringBuilder tableSql = DataBaseTools.createTableSql(getService());
        jdbcTemplate.execute(tableSql);

        // 创建关联表
        List<Field> fields = getFields();
        for (Field field : fields) {
            if (field instanceof Many2manyField) {
                Many2manyField manyField = (Many2manyField) field;
                StringBuilder table = manyField.createTable();
                jdbcTemplate.execute(table);
            }
        }
    }

    /**
     * 创建字段信息
     *
     * @param serviceId 表id
     */
    public void insertFieldInfo(PrimaryKey serviceId) {
        List<Field> fields = getFields();
        for (Field field : fields) {
            field.insertFieldInfo(serviceId);
        }
    }

    /**
     * 创建表记录信息
     */
    public PrimaryKey insertTableInfo(PrimaryKey moduleId) {
        RecordRow row = RecordRow.build();
        row.put("moduleId", getPrimaryKeyValue(moduleId));
        row.put("name", getServiceName());
        row.put("tableName", getServiceTableName());
        row.put("label", getLabel());
        return context.getServiceBean("base.service").insert(row);
    }

    public void dropTable() {
        StringBuilder tableSql = DataBaseTools.dropTableSql(getService());
        jdbcTemplate.execute(tableSql);
        List<Field> fields = getFields();
        for (Field field : fields) {
            if (field instanceof Many2manyField) {
                Many2manyField manyField = (Many2manyField) field;
                StringBuilder table = manyField.dropTable();
                jdbcTemplate.execute(table);
            }
        }
    }

    protected Boolean existTable() {
        StringBuilder sql = DataBaseTools.existTable(getService());
        return jdbcTemplate.executeScalar(sql, Integer.class) != 0;
    }

    /*
     * description: 判断表此字段值是否存在(去重）
     * version: 1.0
     * date: 2022/3/22 11:58
     * author: AN
     *
     * @param field
     * @param value 值
     * @return java.lang.Boolean
     */
    public Boolean existTableFieldValue(Field field, Object value) throws AvalonException {
        return selectOne(Condition.equalCondition(field.getFieldName(), value)) != null;
    }

    public Boolean existTableFieldValue(Condition condition) throws AvalonException {
        return selectOne(condition) != null;
    }

    protected Boolean existField(Field field) {
        StringBuilder sql = DataBaseTools.existField(getService(), field);
        return jdbcTemplate.executeScalar(sql, Integer.class) != 0;
    }

    protected Boolean existField(String fieldName) {
        Field field = getField(fieldName);
        return existField(field);
    }

    /**
     * 升级表结构
     */
    public void upgradeTable() {

        if (existTable()) {
            List<Field> fields = getFields();

            for (Field field : fields) {
                if (field.isPrimaryKey()) continue;
                StringBuilder sql = new StringBuilder();
                if (existField(field)) {
                    sql.append(DataBaseTools.modifyColumn(getService(), field));
                } else {
                    sql.append(DataBaseTools.addColumn(getService(), field));
                }
                jdbcTemplate.execute(sql);
            }

        } else {
            createTable();
        }


    }

    public RecordRow getDefaultValueAll() {

        RecordRow recordRow = new RecordRow();
        getFieldMap().forEach((s, field) -> {
            if (field.getName().equals(CREATE_TIME) ||
                    field.getName().equals(CREATOR) ||
                    field.getName().equals(UPDATE_TIME) ||
                    field.getName().equals(UPDATER) ||
                    field.getName().equals(NAME) ||
                    field.getName().equals(ID)
            ) return;
            if (ObjectUtils.isNotNull(field.getDefaultValue())) {
                recordRow.put(field.getName(), field.getDefaultValue().getDefault());
            }
        });
        return recordRow;
    }

    public FieldHashMap getIsRequiredAll() {
        FieldHashMap requiredFields = new FieldHashMap();
        getFieldMap().forEach((s, field) -> {
            if (field.getFieldName().equals(UPDATE_TIME) || field.getFieldName().equals(UPDATER)) return;
            if (field.isRequired()) {
                requiredFields.put(s, field);
            }
        });
        return requiredFields;
    }

    @Override
    public AbstractService getServiceBean(String serviceName) {
        return context.getServiceBean(serviceName);
    }

    public AbstractService getService() {
        return context.getServiceBean(getServiceName());
    }

    @Override
    public String getAlias(AbstractAliasSupport abstractAliasSupport) {
        return abstractAliasSupport.getAlias(getService());
    }

    @Override
    public FieldValue getFieldValue(Field field, Object id) {
        String name = field.getName();

        RecordRow row = selectOne(name, id);

        return row.get(field);
    }

    /**
     * 获取字段的总和 只能是数值字段
     *
     * @param field
     * @param condition
     * @return
     */
    public FieldValue getSumFieldValue(Field field, Condition condition) {
        return getSumFieldValue(field.getName(), condition);
    }

    /**
     * 获取字段的总和 只能是数值字段
     *
     * @param fieldName
     * @param condition
     * @return
     */
    public FieldValue getSumFieldValue(String fieldName, Condition condition) {

        SelectBuilder selectBuilder = DataBaseTools.selectSql(this.getService(), fieldName, condition);
        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(selectBuilder.getSumSql(),
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectBuilder);

        if (record.size() == 0) {
            return null;
        }

        return record.get(0).get(FieldUtils.getJoinDisplayString(fieldName));
    }

    @Override
    public FieldValue getFieldValue(String fieldName, Integer id) {

        RecordRow row = selectOne(fieldName, id);

        return row.get(FieldUtils.getJoinDisplayString(fieldName));
    }


    @Override
    public FieldValue getFieldValue(Field field, Condition condition) {
        String name = field.getName();

        RecordRow row = selectOne(name, condition);

        return row.get(field);
    }

    @Override
    public FieldValue getFieldValue(String fieldName, Condition condition) {

        RecordRow row = selectOne(fieldName, condition);

        return row.get(FieldUtils.getJoinDisplayString(fieldName));
    }

    @Override
    public void updateNumberValue(RecordRow recordRow) {
        FieldValueStatement fieldValueStatement = new FieldValueStatement();
        StringBuilder sql = DataBaseTools.updateNumberSql(getService(), recordRow, null, fieldValueStatement);

        AvalonPreparedStatement avalonPreparedStatement =
                new AutoKeyPreparedStatement(getService(), sql, fieldValueStatement);
        jdbcTemplate.update(avalonPreparedStatement);
    }

    @Override
    public void updateNumberValue(RecordRow recordRow, Integer id) {
        recordRow.put(getPrimaryKeyName(), id);
        updateNumberValue(recordRow);
    }

    @Override
    public void updateNumberValue(RecordRow recordRow, Condition condition) {
        FieldValueStatement fieldValueStatement = new FieldValueStatement();
        StringBuilder sql = DataBaseTools.updateNumberSql(getService(), recordRow, condition, fieldValueStatement);

        AvalonPreparedStatement avalonPreparedStatement =
                new AutoKeyPreparedStatement(getService(), sql, fieldValueStatement);
        jdbcTemplate.update(avalonPreparedStatement);
    }

    @Override
    public void updateNumberValue(Field field, FieldValue value, Integer id) {
        RecordRow recordRow = new RecordRow();
        recordRow.put(field.getName(), value);
        updateNumberValue(recordRow, id);
    }

    @Override
    public void updateNumberValue(String fieldName, FieldValue value, Integer id) {
        RecordRow recordRow = new RecordRow();
        recordRow.put(fieldName, value);
        updateNumberValue(recordRow, id);
    }

    /**
     * 更新数值字段 使用 name = name + value
     *
     * @param field
     * @param value
     * @param condition
     */
    @Override
    public void updateNumberValue(Field field, FieldValue value, Condition condition) {
        RecordRow recordRow = new RecordRow();
        recordRow.put(field, value);
        updateNumberValue(recordRow, condition);
    }

    @Override
    public void updateNumberValue(String fieldName, FieldValue value, Condition condition) {
        RecordRow recordRow = new RecordRow();
        recordRow.put(fieldName, value);
        updateNumberValue(recordRow, condition);
    }

    @Override
    public void updateNumberValue(Field field, Object value, Integer id) {
        updateNumberValue(field, new FieldValue(value), id);
    }

    @Override
    public void updateNumberValue(String fieldName, Object value, Integer id) {
        updateNumberValue(fieldName, new FieldValue(value), id);
    }

    @Override
    public void updateNumberValue(Field field, Object value, Condition condition) {
        updateNumberValue(field, new FieldValue(value), condition);
    }

    @Override
    public void updateNumberValue(String fieldName, Object value, Condition condition) {
        updateNumberValue(fieldName, new FieldValue(value), condition);
    }

    /**
     * 设置字段值 直接保存到数据库
     *
     * @param field
     * @param value
     * @param id
     * @return
     */
    @Override
    public void setFieldValue(Field field, Object value, Object id) {
        Condition condition = Condition.equalCondition(getPrimaryKeyName(), id);
        setFieldValue(field, value, condition);
    }

    @Override
    public void setFieldValue(String fieldName, Object value, Integer id) {
        Condition condition = Condition.equalCondition(getPrimaryKeyName(), id);
        setFieldValue(fieldName, value, condition);
    }

    @Override
    public void setFieldValue(Field field, Object value, Condition condition) {
        RecordRow row = new RecordRow();
        row.put(field, value);
        update(row, condition);
    }

    @Override
    public void setFieldValue(String fieldName, Object value, Condition condition) {
        RecordRow row = new RecordRow();
        row.put(fieldName, value);
        update(row, condition);
    }

    @Override
    public Object getLock(Map mapTable, Object key) {
        if (mapTable.containsKey(key)) {
            return mapTable.get(key);
        }
        synchronized (mapTable) {
            if (mapTable.containsKey(key)) {
                return mapTable.get(key);
            }
            Object lock = new Object();
            mapTable.put(key, lock);
            return lock;
        }
    }

    @Override
    public Record selectLimit(List<String> fields, Condition condition, int limit) throws AvalonException {
        return selectLimit(FieldUtils.getCommaString(fields), condition, limit);
    }

    @Override
    public Record selectLimit(String fields, Condition condition, int limit) throws AvalonException {
        return selectLimit(fields, condition, null, limit);
    }

    @Override
    public Record selectLimit(List<String> fields, Condition condition, String order, int limit) throws AvalonException {
        return selectLimit(FieldUtils.getCommaString(fields), condition, order, limit);
    }

    @Override
    public Record selectLimit(String fields, Condition condition,
                              String order, int limit) throws AvalonException {
        SelectBuilder selectBuilder = DataBaseTools.selectCountSql(getService(),
                fields,
                condition,
                order,
                null);

        SelectPageBuilder selectPageBuilder = new SelectPageBuilder(selectBuilder, 1, limit);

        StringBuilder sql = selectPageBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());

        return jdbcTemplate.select(avalonPrepareStatement, selectPageBuilder);
    }

    @Override
    public Field getParentIdField() {
        return getField(PARENT_ID_NAME);
    }

    @Override
    public Field getParentPathField() {
        return getField(PARENT_PATH_NAME);
    }

    @Override
    public PageInfo selectTreePage(PageParam pageParam,
                                   String fields,
                                   Condition condition) throws AvalonException {
        return selectTreePage(pageParam, fields, null, condition);
    }

    @Override
    public PageInfo selectTreePage(PageParam pageParam,
                                   String fields,
                                   String order,
                                   Condition condition) throws AvalonException {

        fields = appendPrimaryKey(fields);
        Integer size = context.getApplicationConfig().getPageSize();
        if (ObjectUtils.isNotNull(pageParam.getPageSize())) {
            size = pageParam.getPageSize();
        }

        SelectBuilder selectBuilder = DataBaseTools.selectAllSql(getService(),
                fields,
                condition,
                order,
                null);

        SelectTreeBuilder selectTreeBuilder = new SelectTreeBuilder(selectBuilder, pageParam.getPageNum(), size);

        Integer total = jdbcTemplate.selectCount(selectBuilder.getCountSql(), selectBuilder.getFieldValueStatement());

        StringBuilder sql = selectTreeBuilder.getSql();

        AvalonPreparedStatement avalonPrepareStatement = createAvalonPrepareStatement(sql,
                selectBuilder.getFieldValueStatement());
        Record record = jdbcTemplate.select(avalonPrepareStatement, selectTreeBuilder);

        return new PageInfo(record, total, pageParam.getPageNum(), size);
    }

    /**
     * 查询树形结构 分页 对外统一接口 控制层调用
     *
     * @param pageParam
     * @param fields
     * @param order
     * @param conditions
     * @return
     */
    public PageInfo selectTreePageCondition(PageParam pageParam, String fields, String order,
                                            List<PageConditionHigh> conditions) {

        Condition conditionByHighListCondition = getConditionByHighListCondition(conditions);
        return selectTreePage(pageParam, fields, order, conditionByHighListCondition);
    }

    private FieldHashMap fieldFormatMap;

    @Override
    public FieldHashMap getFieldFormatMap() {
        if (ObjectUtils.isNull(fieldFormatMap) || fieldFormatMap.isEmpty()) {
            synchronized (this) {
                if (ObjectUtils.isNull(fieldFormatMap) || fieldFormatMap.isEmpty()) {//双重判断
                    if (ObjectUtils.isNull(fieldFormatMap)) {
                        fieldFormatMap = new FieldHashMap();
                    }
                    FieldHashMap fieldMap1 = getFieldMap();
                    fieldMap1.forEach((fieldName, field) -> {
                        if (field instanceof IFieldFormat) {
                            fieldFormatMap.put(fieldName, field);
                        }
                    });
                }
            }
        }
        return fieldFormatMap;
    }

}
